﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OseaCS
{
    class PostClasH
    {
        //void ResetPostClassify();
        //void PostClassify(int* recentTypes, int domType, int* recentRRs, int width, double mi2, int rhythmClass);
        //int CheckPostClass(int type);
        //int CheckPCRhythm(int type);
    }

    public static class PostClas
    {
        /*****************************************************************************
        FILE:  postclas.cpp
        AUTHOR:	Patrick S. Hamilton
        REVISED:	5/13/2002
          ___________________________________________________________________________

        postclas.cpp: Post classifier
        Copywrite (C) 2002 Patrick S. Hamilton

        This file is free software; you can redistribute it and/or modify it under
        the terms of the GNU Library General Public License as published by the Free
        Software Foundation; either version 2 of the License, or (at your option) any
        later version.

        This software is distributed in the hope that it will be useful, but WITHOUT ANY
        WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
        PARTICULAR PURPOSE.  See the GNU Library General Public License for more
        details.

        You should have received a copy of the GNU Library General Public License along
        with this library; if not, write to the Free Software Foundation, Inc., 59
        Temple Place - Suite 330, Boston, MA 02111-1307, USA.

        You may contact the author by e-mail (pat@eplimited.edu) or postal mail
        (Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
        MA 02143 USA).  For updates to this software, please visit our website
        (http://www.eplimited.com).
          __________________________________________________________________________

        This file contains functions for classifying beats based after the
        following beat is detected.

	        ResetPostClassify() -- Resets static variables used by
		        PostClassify()
	        PostClassify() -- classifies each beat based on six preceding
		        beats and the following beat.
	        CheckPostClass() --  classifys beat type based on the last
		        eight post classifications of that beat.
	        CheckPCRhythm() -- returns the classification of the RR interval
		        for this type of beat based its previous eight RR intervals.

        ****************************************************************/

        //#include "bdac.h"
        //#include "ecgcodes.h"

        // External Prototypes.

        //public static double DomCompare(int newType, int domType) ;
        //public static int GetBeatTypeCount(int type) ;

        // Records of post classifications.

        public static int[,] PostClass = new int[BdacH.MAXTYPES, 8];
        public static int PCInitCount = 0;
        public static int[,] PCRhythm = new int[BdacH.MAXTYPES, 8];

        //public static Match match = new Match();

        /**********************************************************************
         Resets post classifications for beats.
        **********************************************************************/

        public static void ResetPostClassify()
	    {
            int i, j ;
            for(i = 0; i < BdacH.MAXTYPES; ++i)
                for(j = 0; j < 8; ++j)
                    {
                    PostClass[i, j] = 0 ;
                    PCRhythm[i, j] = 0 ;
                    }
            PCInitCount = 0 ;
	    }


        /***********************************************************************
	        Classify the previous beat type and rhythm type based on this beat
	        and the preceding beat.  This classifier is more sensitive
	        to detecting premature beats followed by compensitory pauses.
        ************************************************************************/

        unsafe public static void PostClassify(int *recentTypes, int domType, int *recentRRs, int width, double mi2, int rhythmClass)
	    {
            int lastRC, lastWidth;
            double lasyMI2;
            int regCount, pvcCount, normRR;
            double mi3;

            if (recentTypes[0] == recentTypes[2] && recentTypes[0] != domType && recentTypes[0] != recentTypes[1])
            {
                mi3 = Match.DomCompare(recentTypes[0], domType);
                for (int i = regCount = 0; i < 8; ++i)
                    if (PCRhythm[recentTypes[0]][i] == EcgCodes.NORMAL)
                        regCount++;
                if (mi3 < 2.0 && regCount > 6)
                    domType = recentTypes[0];
            }

            if (PCInitCount < 3)
            {
                ++PCInitCount;
                lastWidth = width;
                lasyMI2 = 0;
                lastRC = 0;
                return;
            }

            if (recentTypes[1] < BdacH.MAXTYPES)
            {
                for( int i = 2; (i < 7) && (recentTypes[i] != recentTypes[i+1]); ++i);
                if ( i == 7)
                    normRR =0;
                else
                    normRR = recentRRs[i];

                for( int i = pvcCount = 0 ; i < 8; ++i)
                    if ( PostClass[recentTypes[1]][i] == EcgCodes.PVC )
                        ++pvcCount;

                for( int i = 7 ; i > 0; --i)
                {
                    PostClass[recentTypes[1]][i] = PostClass[recentTypes[1]][i-1] ;
                    PCRhythm[recentTypes[1]][i] = PCRhythm[recentTypes[1]][i-1] ;
                }

                if (((normRR-(normRR>>3)) >= recentRRs[1]) && 
                    ((recentRRs[0]-(recentRRs[0]>>3))>=normRR) &&
                    (recentTypes[0] == domType) &&
                    (recentTypes[2] ==domType)&&
                    (recentTypes[1] != domType))
                    PostClass[recentTypes[1]][0] = EcgCodes.PVC;  
                else if (((normRR-(normRR>>4)) > recentRRs[1]) &&
                         ((normRR+(normRR>>4)) < recentRRs[0]) &&
                         (((PostClass[recentTypes[1]][1] ==EcgCodes.PVC) && (PostClass[recentTypes[1]][2] == EcgCodes.PVC)) ||
                         (pvcCount >=6)) &&
                         (recentTypes[0] == domType) && (recentTypes[2] ==domType) && (recentTypes[1] != domType))
                        PostClass[recentTypes[1]][0] = EcgCodes.PVC;
                else if ((recentTypes[0] ==domType) && (recentTypes[2] ==domType) && (lasyMI2 > 2.5))
                    PostClass[recentTypes[1]][0] = EcgCodes.UNKNOWN;        
                 else PCRhythm[recentTypes[1]][0] = lastRC ;
           }

           lastWidth = width ;
           lastMI2 = mi2 ;
           lastRC = rhythmClass;
	    }


        /*************************************************************************
	        CheckPostClass checks to see if three of the last four or six of the
	        last eight of a given beat type have been post classified as PVC.
        *************************************************************************/

        public static int CheckPostClass(int type)
	    {
            Int16  pvcs4 = 0, pvcs8 ;

            if(type == BdacH.MAXTYPES)
                return(EcgCodes.UNKNOWN) ;

            for(int i = 0; i < 4; ++i)
                if(PostClass[type, i] == EcgCodes.PVC)
                    ++pvcs4 ;
            for(pvcs8=pvcs4; i < 8; ++i)
                if(PostClass[type, i] == EcgCodes.PVC)
                    ++pvcs8 ;
            if((pvcs4 >= 3) || (pvcs8 >= 6))
                return(EcgCodes.PVC) ;
            else 
                return(EcgCodes.UNKNOWN) ;
            return 0;
	    }


        /****************************************************************************
	        Check classification of previous beats' rhythms based on post beat
	        classification.  If 7 of 8 previous beats were classified as NORMAL
	        (regular) classify the beat type as NORMAL (regular).
	        Call it a PVC if 2 of the last 8 were regular.
        ****************************************************************************/

        public static int CheckPCRhythm(int type)
	    {
            Int16 normCount, n ;


            if(type == BdacH.MAXTYPES)
                return(EcgCodes.UNKNOWN) ;
            if(Match.GetBeatTypeCount(type) < 9)
                n = Match.GetBeatTypeCount(type) - 1;
            else 
                n = 8;
 
            for( int i = normCount = 0 ; i < n; ++i)
                if ( PCRhythm[type,i] == EcgCodes.NORMAL)
                    ++normCount;
            if (normCount >=7)
                return(EcgCodes.NORMAL);

            if(((normCount == 0) && (n < 4 )) ||
                ((normCount < 1) && (n >=4) && (n < 7)) ||
                ((normCount <= 2) && (n >= 7)))
                return(EcgCodes.PVC) ;
            return(EcgCodes.UNKNOWN);

	    }

    }
}
